package com.employment.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * JDK 21虚拟线程工具类
 * 
 * @author employment
 * @since 2024-01-01
 */
@Slf4j
@Component
public class VirtualThreadUtil {

    private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

    /**
     * 检查是否支持虚拟线程
     */
    public static boolean isVirtualThreadSupported() {
        try {
            String javaVersion = System.getProperty("java.version");
            // 处理类似 "1.8.0_292" 或 "11.0.12" 或 "21" 的版本号
            String[] versionParts = javaVersion.split("\\.");
            int majorVersion;
            if (versionParts[0].equals("1")) {
                // Java 8 之前的版本格式 "1.x.x_xxx"
                majorVersion = Integer.parseInt(versionParts[1]);
            } else {
                // Java 9+ 的版本格式 "x.x.x"
                majorVersion = Integer.parseInt(versionParts[0]);
            }
            return majorVersion >= 21;
        } catch (Exception e) {
            log.warn("检查虚拟线程支持时发生异常", e);
            return false;
        }
    }

    /**
     * 获取当前线程统计信息
     */
    public static ThreadInfo getThreadInfo() {
        return ThreadInfo.builder()
                .totalThreadCount(threadMXBean.getThreadCount())
                .peakThreadCount(threadMXBean.getPeakThreadCount())
                .daemonThreadCount(threadMXBean.getDaemonThreadCount())
                .virtualThreadSupported(isVirtualThreadSupported())
                .jdkVersion(System.getProperty("java.version"))
                .build();
    }

    /**
     * 创建虚拟线程执行器
     */
    public static ExecutorService createVirtualThreadExecutor() {
        if (isVirtualThreadSupported()) {
            try {
                // 使用反射调用Executors.newVirtualThreadPerTaskExecutor()方法
                Method method = Executors.class.getMethod("newVirtualThreadPerTaskExecutor");
                return (ExecutorService) method.invoke(null);
            } catch (Exception e) {
                log.warn("反射调用newVirtualThreadPerTaskExecutor失败，使用固定线程池", e);
                return Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
            }
        } else {
            log.warn("当前JDK版本不支持虚拟线程，使用固定线程池");
            return Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
        }
    }

    /**
     * 执行异步任务（使用虚拟线程）
     */
    public static void executeAsync(Runnable task) {
        if (isVirtualThreadSupported()) {
            try {
                // 使用反射调用Thread.ofVirtual().start(task)
                Class<?> threadBuilderClass = Class.forName("java.lang.Thread$Builder");
                Method ofVirtualMethod = Thread.class.getMethod("ofVirtual");
                Object threadBuilder = ofVirtualMethod.invoke(null);
                Method startMethod = threadBuilderClass.getMethod("start", Runnable.class);
                startMethod.invoke(threadBuilder, task);
            } catch (Exception e) {
                log.warn("反射调用Thread.ofVirtual().start失败，使用普通线程", e);
                new Thread(task).start();
            }
        } else {
            new Thread(task).start();
        }
    }

    /**
     * 线程信息数据类
     */
    @lombok.Data
    @lombok.Builder
    public static class ThreadInfo {
        private int totalThreadCount;
        private int peakThreadCount;
        private int daemonThreadCount;
        private boolean virtualThreadSupported;
        private String jdkVersion;
    }

    /**
     * 记录线程状态信息
     */
    public static void logThreadStatus() {
        ThreadInfo info = getThreadInfo();
        log.info("=== 线程状态统计 ===");
        log.info("JDK版本: {}", info.getJdkVersion());
        log.info("虚拟线程支持: {}", info.isVirtualThreadSupported());
        log.info("当前线程总数: {}", info.getTotalThreadCount());
        log.info("峰值线程数: {}", info.getPeakThreadCount());
        log.info("守护线程数: {}", info.getDaemonThreadCount());
        log.info("==================");
    }
}